#include <stdlib.h>
#include "snri_module.h"

int (*_snricall_fpref)(int, ...);

/**
 * Returns all IPs available to this node 
 * 
 * @param addrs Output parameter for the in_addr_t array
 * @return Number of addresses assigned
 */
int snri_getips(in_addr_t ** addrs) {
	int num_addrs;
	
	if(_snricall(SNRICALL_GETIP, &num_addrs, addrs))
		return num_addrs;
	else
		return SNRI_ERROR;
}

/**
 * Returns the first IP in the list given by snri_getips()
 * 
 * @return IP of this node
 */
in_addr_t snri_getip() {
	in_addr_t * addrs;
	
	if(snri_getips(&addrs) > 0 && addrs)
		return addrs[0];
	else
		return SNRI_ERROR;
}


/**
 * Creates a datagram socket. 
 * You must have created a socket for any SNRI communications
 * 
 * @return the socket identifier
 */ 
int snri_datagram_socket(in_addr_t bind_address, int port, snri_network_message_callback_fp callback_function) {
	int socket_id;
	if(_snricall(SNRICALL_DATAGRAM_SOCKET, bind_address, port, callback_function, &socket_id))
		return socket_id;
	else
		return SNRI_ERROR;
}

/**
 * Sends a datagram to a given destination using a datagram socket
 */
int snri_datagram_send(int datagram_socket, in_addr_t dest_addr, int dest_port, unsigned int data_length, char * data) {
	return _snricall(SNRICALL_DATAGRAM_SEND, datagram_socket, dest_addr, dest_port, data_length, data) ? 0 : SNRI_ERROR;
}

/**
 * @param t Will be filled with the current system time
 */
int snri_gettime(struct timeval *t) {
	return _snricall(SNRICALL_GETTIME, t);
}

/**
 * @param socket Socket that will be closed
 */
int snri_close(int socket) {
	return _snricall(SNRICALL_CLOSE, socket) ? 0 : SNRI_ERROR;
}

/**
 * Creates a timer that will expire after the given delay
 * 
 * @param milli_delay Number of milliseconds after which this timer will expire
 * @param callback_function The function that will be called when this timer expires
 */
int snri_timer_create(int milli_delay, snri_timer_callback_fp callback_function, void * cb_arg) {
	int timer_id;
	if(_snricall(SNRICALL_CREATE_TIMER, milli_delay, callback_function, cb_arg, &timer_id))
		return timer_id;
	else
		return SNRI_ERROR;
}

/**
 * Destroys the timer with the given ID (prevents it from executing '
 */
int snri_timer_destroy(int timer_id) {
	return _snricall(SNRICALL_DESTROY_TIMER, timer_id) ? 0 : SNRI_ERROR;
}

/**
 * Schedules this node for deletion
 */
int snri_die() {
	return _snricall(SNRICALL_DIE) ? 0 : SNRI_ERROR;
}

/**
 * Logs some message
 */
int snri_log(int level, char * fmt, ...) {
	static char buffer[2048];
	va_list arg;
	int len;
	
	va_start(arg, fmt);
	len = vsnprintf(buffer, sizeof(buffer), fmt, arg);
	va_end(arg);

	if(len > sizeof(buffer))
		len = sizeof(buffer)-1;

	snri_log_binary(level, buffer, len);
}

/**
 * Logs some binary data
 */
int snri_log_binary(int level, char * data, int data_size) {
	_snricall(SNRICALL_LOG,level, data, data_size);
}

